//
//  RxTestViewController.swift
//  swift3.0Exercise
//
//  Created by pactera on 2018/9/10.
//  Copyright © 2018年 BMW. All rights reserved.
//

import UIKit
import RxSwift

class RxTestViewController: UIViewController {

    @IBOutlet weak var button: UIButton!
    
    @objc let person = Person()
    
    let disposeBag = DisposeBag()
    
    var observation: NSKeyValueObservation!
    
    typealias JSON = Any

    override func viewDidLoad() {
        super.viewDidLoad()

        flatMap()

    }

    private func flatMap() {
        let subject1 = BehaviorSubject(value: "A")
        let subject2 = BehaviorSubject(value: "1")
        let variable = Variable(subject1)
        
        variable
        .asObservable()
        .flatMap { $0 }
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
        
        subject1.onNext("B")
        subject1.onNext("C")
        subject2.onNext("2")

        variable.value = subject2
        subject1.onNext("D")
        subject2.onNext("3")
        subject2.onNext("4")
        subject2.onCompleted()
    }
    
    private func distinctUntil() {
        Observable.of("A","B","B","C","C","D")
        .distinctUntilChanged()
            .subscribe(onNext: {
                print($0)
            })
        .disposed(by: disposeBag)
    }
    
    private func debug() {
        let sequence = Observable<Int>.create { (observer) -> Disposable in
            observer.onNext(0)
            observer.onCompleted()
            return Disposables.create()
        }
        sequence
            .debug()
            .subscribe()
            .disposed(by: disposeBag)
    }
    
    private func concatMap() {
        let subject1 = BehaviorSubject(value: "111")
        let subject2 = BehaviorSubject(value: "AAA")
        
        let variable = Variable(subject1)
        variable
            .asObservable()
            .concatMap { $0 }
            .subscribe(onNext: {
            print($0)
        })
            .disposed(by: disposeBag)
        
        subject1.onNext("222")
        subject1.onNext("333")
        
        variable.value = subject2
        subject2.onNext("ignored")
        subject2.onNext("BBB")
        subject1.onCompleted()
        subject2.onNext("CCC")
    }
    
    private func concat() {
        let subject1 = BehaviorSubject(value: "AAA")
        let subject2 = BehaviorSubject(value: "111")
        
        let variable = Variable(subject1)
        variable.asObservable().concat().subscribe(onNext: {
            print("variable = \($0)")
        }).disposed(by: disposeBag)
        
        subject1.onNext("BBB")
        subject1.onNext("CCC")
        
        variable.value = subject2
        
        subject2.onNext("222")
        subject2.onNext("333")
        subject1.onCompleted()
        subject2.onNext("444")
    }
    
    
    private func combineLatest() {
        let first = PublishSubject<String>()
        let second = PublishSubject<String>()
        
        Observable.combineLatest(first, second) {
            print("combine = \($0 + $1)")
            }.subscribe(onNext: {
                print("subscribe = \($0)")
            }).disposed(by: disposeBag)
        
        first.onNext("AAA")
        second.onNext("111")
        first.onNext("BBB")
        second.onNext("222")
        first.onCompleted()
    }
    
    private func behaviorSubject() {
        let subject = BehaviorSubject<String>(value: "LPZ")
        subject.subscribe(onNext: {
            print("event1 = \($0)")
        }).disposed(by: disposeBag)
        
        subject.onNext("AAA")
        subject.onNext("BBB")
        
        subject.subscribe(onNext: {
            print("event2 = \($0)")
        }).disposed(by: disposeBag)
        
        subject.onNext("CCC")
        subject.onNext("DDD")
        
        subject.subscribe(onNext: {
            print("event3 = \($0)")
        }).disposed(by: disposeBag)
        subject.onNext("EEE")
        subject.onNext("FFF")
    }

    private func replaySubject() {
        let subject = ReplaySubject<String>.createUnbounded()
        subject.subscribe(onNext: {
            print("event1 = \($0)")
        }).disposed(by: disposeBag)
        
        subject.onNext("AAA")
        subject.onNext("BBB")
        
        subject.subscribe(onNext: {
            print("event2 = \($0)")
        }).disposed(by: disposeBag)
        
        subject.onNext("CCC")
        subject.onNext("DDD")
        subject.onCompleted() // 可有可无
    }
    
    private func publishSubject() {
        let subject = PublishSubject<String>()
        subject.subscribe {
            print("event1 = \($0)")
        }.disposed(by: disposeBag)
        
        subject.onNext("kkk")
        subject.onNext("aaa")
        
        subject.subscribe(onNext: {
            print("event2 = \($0)")
        }).disposed(by: disposeBag)
        
        subject.onNext("lpz")
        subject.onNext("🐻")
        subject.onCompleted()
   /*  输出 有区别
        event1 = next(kkk)
        event1 = next(aaa)
        event1 = next(lpz)
        event2 = lpz
        event1 = next(🐻)
        event2 = 🐻
        event1 = completed
*/
    }
    
    private func asyncSubject() {
        let subject = AsyncSubject<String>()
        subject.subscribe(onNext: {
          print($0)
        }).disposed(by: disposeBag)
        
        subject.onNext("3")
        subject.onNext("kkk")
        subject.onNext("🐈")
        subject.onCompleted()
    }

    private func single() {
        let json: Single<JSON> = Single.create { (observer) -> Disposable in
            let task = URLSession.shared.dataTask(with: URL(string: "https://www.baidu.com")!, completionHandler: { (data, _, error) in
                if let error = error {
                    observer(.error(error))
                    return
                }
                guard let data = data, let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else {
                    return
                }
                observer(.success(data))
            })
            task.resume()
            return Disposables.create {
                task.cancel()
            }
        }
    }
    
    private func block() {
        let json: Observable<JSON> = Observable.create { (observer) -> Disposable in
            let task = URLSession.shared.dataTask(with: URL(string: "https://www.baidu.com")!, completionHandler: { (data, response, error) in
                guard let error = error else { return }
                observer.onError(error)
                
                guard let data = data, let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else {
//                    observer.onError(DataError.cantParseJSON)
                    return
                }
                observer.onNext(jsonObject)
                observer.onCompleted()
            })
            task.resume()
            return Disposables.create {
                task.cancel()
            }
        }
        
        json.subscribe(onNext: { json in
            print(json)
        },onError: { error in
            print(error)
        },onCompleted: {
            print("complete")
        }).disposed(by: disposeBag)
    }
    
    private func createSequence() {
        let numbers: Observable<Int> = Observable.create { (observer) -> Disposable in
            observer.onNext(0)
            observer.onNext(1)
            observer.onNext(2)
            observer.onCompleted()
            return Disposables.create()
        }
        
        _ = numbers.subscribe { (event) in
            
            print("event = \(event)")
        }
    }
    
    private func firstTest() {
        //        target - action
        _ = button.rx.tap.subscribe {
            print("button tapped")
        }
        // 不调用的，必须加onNext:
        
        let observable: Observable<Void> = button.rx.tap.asObservable()
        
        observable.subscribe(onNext: {
            print("被点击了")
        }).disposed(by: disposeBag)
        
        _ = button.rx.tap.subscribe(onNext: {
            print($0)
        })
        
        //        delegate
        _ = URLSession.shared.rx.data(request: URLRequest(url: URL(string: "https://www.baidu.com")!)).subscribe(onNext: { data in
            print("data is \(data)")
        }, onError: { error in
            print("error is \(error)")
        })
        
        //        Notification
        _ = NotificationCenter.default.rx.notification(.UIApplicationWillEnterForeground).subscribe {
            print("notification is \($0)")
        }
        
        //        KVO
        observation = person.observe(\.age) { (person, change) in
            print("person = \(person), change = \(change)")
        }
        
        _ = person.rx.observe(String.self, #keyPath(Person.name)).subscribe {
            print("KVOname = \($0)")
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        person.name = "lsn"
        person.age = 15
    }
    
  

  
}
